/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package technotheist.imgcog.base;

import com.amd.aparapi.Kernel;
import java.util.ArrayList;

/**
 * This project is the intellectual property and only to be used under license
 * guidelines. Please see the containing license.txt file for license
 * information and availability of use. The author takes no responsibility for
 * any damage or non-functionality caused by use of this software.
 *
 * For use of any content with a different license, please contact the author.
 *
 * @author Mitchel Strachan <technotheist@gmail.com>
 */
public abstract class Module extends Provider implements Receiver  {

    private Runner runner;



    protected Runner runner() {
        return runner;
    }

    private Dimension layer0Size;
    private boolean layer0Dirty = true;
    private boolean layerNDirty = true;
    
    @Override
    protected final float[] getOutput() {
        if(layerNDirty) {
            runner().get(runner().layerNOutput);
            layerNDirty = false;
        }
        return runner().layerNOutput;
    }
    
    @Override
    public Dimension getInputSize() {
        return layer0Size;
    }
    
    @Override
    public boolean addProvider(Provider p) {
        
        if(p.getOutputSize().isLessThan(this.getInputSize())) {
            
        }
        
        
        return false;
    }
    
    @Override
    public boolean removeProvider(Provider p) {
        
        
        return false;
    }
    
    @Override
    public Provider removeProvider(int p) {
        
        return null;        
    }

    
    
    
    private class InputDef {
        Provider provider;
        Dimension providerStart;
        Dimension thisStart;
        Dimension len;

        public InputDef(Provider provider, Dimension providerStart, Dimension thisStart, Dimension len) {
            this.provider = provider;
            this.providerStart = providerStart;
            this.thisStart = thisStart;
            this.len = len;
        }
        
    }
    protected abstract void process();

    public abstract class Runner extends Kernel {

        protected final int layer0Size;
        protected final int layerNSize;
        protected final float[] layer0Nodes;
        protected final float[] layerNOutput;

        protected Runner(int inputSize, int outputSize) {
            this.layer0Size = inputSize;
            this.layerNSize = outputSize;
            layer0Nodes = new float[inputSize];
            layerNOutput = new float[outputSize];
        }

        protected Runner(BaseConfig config) {
            this.layer0Size = config.getInputSize();
            this.layerNSize = config.getOutputSize();
            layer0Nodes = new float[layer0Size];
            layerNOutput = new float[layerNSize];
        }

        protected final float uniLinFunc(float x) {
            return max(0, x);
        }

        protected final float biLinFunc(float x) {
            return x;
        }

        protected final float uniLinCappedFunc(float x) {
            return min(1, max(0, x));
        }

        protected final float biLinCappedFunc(float x) {
            return min(1, max(-1, x));
        }

        protected final float biSigFunc(float x) {
            return -1f + 2f / (1 + exp(x));
        }

        protected final float uniSigFunc(float x) {
            return 1f / (1 + exp(x));
        }

        protected final float uniLinDeriv(float fx) {
            if (fx > 0.0f) {
                return 1;
            }
            return 0;
        }

        protected final float biLinDeriv(float fx) {
            return 1;
        }

        protected final float uniLinCappedDeriv(float fx) {
            if (fx > 0.0f && fx < 1.0f) {
                return 1;
            }
            return 0;
        }

        protected final float biLinCappedDeriv(float fx) {
            if (fx > -1.0f && fx < 1.0f) {
                return 1;
            }
            return 0;
        }

        protected final float biSigDeriv(float fx) {
            return 0.5f * (1f + fx) * (1f - fx);
        }

        protected final float uniSigDeriv(float fx) {
            return fx * (1f - fx);
        }

        protected int index2D(int x, int y, int Y) {
            return y + x * Y;
        }

        protected int index3D(int x, int y, int z, int Y, int Z) {
            return z + Z * (y + x * Y);
        }

        protected int x2D(int index, int Y) {
            return index / Y;
        }

        protected int y2D(int index, int Y) {
            return index % Y;
        }

        protected int x3D(int index, int Y, int Z) {
            return index / (Y * Z);
        }

        protected int y3D(int index, int Y, int Z) {
            return (index / Z) % Y;
        }

        protected int z3D(int index, int Z) {
            return index % Z;
        }
    }
}
